package com.tbit.main.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.MachineOpLog;
import com.tbit.common.entity.UserOpLog;
import com.tbit.common.utils.TraceUtil;
import com.tbit.main.dao.log.MachineOpLogDao;
import com.tbit.main.dao.log.UserOpLogDao;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author <a href="mailto:zheng.zebiao@tbit.com.cn">zb</a>
 * @since 2024/11/25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MachineOpLogService extends ServiceImpl<MachineOpLogDao, MachineOpLog> {
    final MachineOpLogDao machineOpLogDao;
    final UserOpLogDao userOpLogDao;

    public void insertSingle(MachineOpLog machineOpLog) {
        try {
            addTraceIdToDetail(machineOpLog);
            machineOpLogDao.insert(machineOpLog);

            // 顺便插入用户操作日志
            String detail = ObjectUtil.defaultIfNull(machineOpLog.getDetail(), "");
            UserOpLog userOpLog = UserOpLog.builder()
                    .accountId(machineOpLog.getAccountId())
                    .operation(machineOpLog.getOperation())
                    .opType(machineOpLog.getOpType())
                    .opUser(machineOpLog.getOpUser())
                    .opUserPhone(machineOpLog.getOpUserPhone())
                    .opPlatform(OperationPlatform.MAINTAIN.code)
                    .opTime(LocalDateTime.now())
                    .result(machineOpLog.getResult())
                    .detail(detail + (detail.isEmpty() ? "" : "\n") + "车辆编号: " + machineOpLog.getUserCode() + "\n中控编号: " + machineOpLog.getMachineNO())
                    .build();
            userOpLogDao.insert(userOpLog);
        } catch (Exception e) {
            log.error("[车辆操作日志] 插入失败: {}", machineOpLog, e);
        }
    }

    public void insertBatch(List<MachineOpLog> machineOpLogs) {
        try {
            for (MachineOpLog machineOpLog : machineOpLogs) {
                addTraceIdToDetail(machineOpLog);
            }
            machineOpLogDao.batchInsert(machineOpLogs);

            // 顺便插入用户操作日志
            List<UserOpLog> userOpLogs = machineOpLogs.stream()
                    .map(machineOpLog -> {
                        String detail = ObjectUtil.defaultIfNull(machineOpLog.getDetail(), "");
                        return UserOpLog.builder()
                                .accountId(machineOpLog.getAccountId())
                                .operation(machineOpLog.getOperation())
                                .opType(machineOpLog.getOpType())
                                .opUser(machineOpLog.getOpUser())
                                .opUserPhone(machineOpLog.getOpUserPhone())
                                .opPlatform(OperationPlatform.MAINTAIN.code)
                                .opTime(LocalDateTime.now())
                                .result(machineOpLog.getResult())
                                .detail(detail + (detail.isEmpty() ? "" : "\n") + "车辆编号: " + machineOpLog.getUserCode() + "\n中控编号: " + machineOpLog.getMachineNO())
                            .build();
                    })
                    .collect(Collectors.toList());
            userOpLogDao.batchInsert(userOpLogs);
        } catch (Exception e) {
            log.error("[车辆操作日志] 插入失败，失败条数: {}", machineOpLogs.size(), e);
        }
    }

    private void addTraceIdToDetail(MachineOpLog machineOpLog) {
        StringBuilder detail = new StringBuilder(ObjectUtil.defaultIfNull(machineOpLog.getDetail(), ""));
        String traceId = TraceUtil.getTraceIdByLocal();
        if (traceId != null) {
            if (detail.length() > 0) {
                detail.append("\n");
            }
            detail.append("TraceID: ")
                    .append(traceId);
        }
        machineOpLog.setDetail(detail.length() > 0 ? detail.toString() : null);
    }
}
